﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MethodWorx.CMS.Content;
using MethodWorx.CMS.Plugins;
using MethodWorx.CMS.Membership;

namespace MethodWorx.CMS.Administration
{
    /// <summary>
    /// Provides an API for interacting with certain functions the CMS provides when in a Hosted Application mode
    /// </summary>
    public class HostedApplicationService
    {
        IPageTemplateRepository pageTemplates;
        IContentTemplateRepository contentTemplates;
        IPageRepository pages;
        IContentItemRepository contentItems;
        IPluginUserDataRepository pluginUserData;
        IUserRepository users;
        /*IRoleRepository roles;*/
        HostedApplicationConfigurationValues configurationValues;

        public HostedApplicationService(
            IPageTemplateRepository pageTemplates, 
            IContentTemplateRepository contentTemplates,
            IPageRepository pages,
            IContentItemRepository contentItems,
            IPluginUserDataRepository pluginUserData,
            IUserRepository users,
            /*IRoleRepository roles,*/
            HostedApplicationConfigurationValues configurationValues
            )
        {
            this.pages = pages;
            this.pageTemplates = pageTemplates;
            this.contentTemplates = contentTemplates;
            this.contentItems = contentItems;
            this.pluginUserData = pluginUserData;
            this.users = users;
            /*this.roles = roles;*/
            this.configurationValues = configurationValues;
        }

        public HostedApplicationConfigurationValues ConfigurationValues { get { return this.configurationValues; } }

        public HostedApplicationUsage GetUsage()
        {
            return new HostedApplicationUsage()
            {
                ContentSize = this.GetContentSize(false),
                DeletedItems = this.GetDeletedItems(),
                SchemaSize = this.GetSchemaSize(false),
                PluginData = this.GetPluginData(false)
            };
        }

        private decimal GetPluginData(bool deleted)
        {
            decimal size = 0;
            foreach (var ud in this.pluginUserData.All().Where(p => p.Deleted == deleted))
            {
                size += ud.UserData.Base64SerializeUsingXml().Length;
            }

            return size;
        }

        private decimal GetDeletedItems()
        {
            return  this.GetContentSize(true) + 
                    this.GetSchemaSize(true) + 
                    this.GetPluginData(true);
        }

        private decimal GetSchemaSize(bool deleted)
        {
            decimal size = 0;

            foreach (var pageTemplate in pageTemplates.All().Where(p => p.Deleted == deleted))
            {
                //
                //  ok, lets add it up
                size += pageTemplate.Name.Length;
                size += (pageTemplate.Template ?? "").Length;

                foreach (var property in pageTemplate.Properties)
                {
                    size += property.Name.Length;
                    if (property.Custom != null)
                        size += property.Custom.Base64SerializeUsingXml().Length;
                }
            }

            foreach (var contentTemplate in contentTemplates.All().Where(ci => ci.Deleted == deleted))
            {
                //  ok, lets add it up
                size += contentTemplate.Name.Length;
                foreach (var property in contentTemplate.Properties)
                {
                    size += property.Name.Length;
                    if (property.Custom != null)
                        size += property.Custom.Base64SerializeUsingXml().Length;
                }
            }

            return size;
        }

        private decimal GetContentSize(bool deleted)
        {
            decimal contentSize = 0;

            foreach (Page page in pages.All().Where(p => p.Status == ContentStatus.Deleted))
            {
                //
                //  ok, lets add it up
                contentSize += page.Name.Length;
                contentSize += (page.PublishedTemplate ?? "").Length;
                foreach (var property in page.Properties)
                {
                    contentSize += property.Name.Length;
                    if(property.Value != null)
                        contentSize += property.Value.Base64SerializeUsingXml().Length;
                }
                foreach (var property in page.PublishedProperties)
                {
                    contentSize += property.Name.Length;
                    if (property.Value != null)
                        contentSize += property.Value.Base64SerializeUsingXml().Length;
                }
            }

            foreach (var contentItem in contentItems.All().Where(ci => ci.Deleted == deleted))
            {
                contentSize += contentItem.Name.Length;
                foreach (var property in contentItem.Properties)
                {
                    contentSize += property.Name.Length;
                    if (property.Value != null)
                        contentSize += property.Value.Base64SerializeUsingXml().Length;
                }
                foreach (var property in contentItem.PublishedProperties)
                {
                    contentSize += property.Name.Length;
                    if (property.Value != null)
                        contentSize += property.Value.Base64SerializeUsingXml().Length;
                }
            }

            return contentSize;
        }

    }
}
